package com.family.pedigree.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.family.pedigree.domain.FamilyClan;
import com.family.pedigree.domain.FamilyNode;
import com.family.pedigree.domain.dto.FamilyNodeDto;
import com.family.pedigree.domain.vo.FamilyClanQuery;
import com.family.pedigree.mapper.FamilyClanMapper;
import com.family.pedigree.mapper.FamilyNodeMapper;
import com.family.pedigree.service.IFamilyClanService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 家族族谱信息
 * 服务实现类
 * </p>
 *
 * @author forever
 * @since 2024-11-10
 */
@Service
@RequiredArgsConstructor
public class FamilyClanServiceImpl extends ServiceImpl<FamilyClanMapper, FamilyClan> implements IFamilyClanService {


    //节点信息
    private final FamilyNodeMapper nodeMapper;

    /**
     * 查询全部家族数
     *
     * @param clanVo 查询条件
     * @return 家族树结构
     */
    @Override
    public List<FamilyNodeDto> getAllTree(FamilyClanQuery clanVo) {

        //获取家族列表,顺序返回
        List<FamilyClan> topFamilyList = getTopFamily();

        if (CollUtil.isEmpty(topFamilyList)) return CollUtil.newArrayList();

        List<FamilyNodeDto> result = CollUtil.newArrayList();
        buildTree(topFamilyList, result);

        return result;
    }

    @Override
    public Map<String, Object> countByType(String type) {
        Map<String, Object> resultMap = new HashMap<>();
        List<FamilyNode> nodeList;
        LambdaQueryWrapper<FamilyNode> eq = Wrappers.<FamilyNode>lambdaQuery().eq(FamilyNode::getIsDelete, 0);
        switch (type) {
            case "人数":
                nodeList = nodeMapper.selectList(eq);
                if (CollUtil.isEmpty(nodeList)) break;
                Map<String, List<FamilyNode>> userMap = nodeList.stream().collect(Collectors.groupingBy(FamilyNode::getFamilyName));
                userMap.forEach((k, v) -> {
                    resultMap.put(k, v.size());
                });
                break;
            case "性别":
                nodeList = nodeMapper.selectList(eq);
                Map<String, List<FamilyNode>> suserMap = nodeList.stream().filter(x -> Objects.nonNull(x.getFamilyName())).collect(Collectors.groupingBy(FamilyNode::getFamilyName));
                suserMap.forEach((k, v) -> {
                    Map<String, Long> sexMap = new HashMap<>();
                    Map<Boolean, Long> genderCount = v.stream()
                            .collect(Collectors.partitioningBy(x -> "1".equals(x.getSex()), Collectors.counting()));
                    sexMap.put("女", genderCount.get(true));
                    sexMap.put("男", genderCount.get(false));
                    resultMap.put(k, sexMap);
                });
                break;
            case "代":
                nodeList = nodeMapper.selectList(eq);
                if (CollUtil.isEmpty(nodeList)) break;
                Map<String, Map<Integer, List<FamilyNode>>> collect = nodeList.stream()
                        .collect(Collectors.groupingBy(FamilyNode::getFamilyName, Collectors.groupingBy(FamilyNode::getFamilyRank)));
                collect.forEach((k, v) -> {
                    Map<String, Integer> map = new HashMap<>();
                    v.forEach((k1, v1) -> {
                        map.put("第" + k1 + "代", v1.size());
                    });
                    resultMap.put(k, map);
                });
                break;
            default:
                break;
        }
        return resultMap;
    }

    private List<FamilyClan> getTopFamily() {
        return list(Wrappers.<FamilyClan>lambdaQuery().le(FamilyClan::getFamilyRank, 1).or().isNull(FamilyClan::getFamilyRank));
    }


    private void buildTree(List<FamilyClan> familyList, List<FamilyNodeDto> result) {
        familyList.forEach(v -> {

            //获取当前代节点的人
            List<FamilyNode> nodeList = nodeMapper.selectList(Wrappers.<FamilyNode>lambdaQuery().eq(FamilyNode::getFamilyId, v.getFamilyId()));
            if (CollUtil.isEmpty(nodeList)) return;
            for (FamilyNode node : nodeList) {
                FamilyNodeDto dto = BeanUtil.copyProperties(node, FamilyNodeDto.class);
                List<FamilyNode> childList = nodeMapper.selectList(Wrappers.<FamilyNode>lambdaQuery().eq(FamilyNode::getIsDelete, 0).eq(FamilyNode::getParentId, node.getNodeId()));
                if (CollUtil.isEmpty(childList)) continue;
                List<FamilyNodeDto> childFamilyList = buildChildFamilyList(node.getNodeId());
                dto.setChildren(childFamilyList);
                result.add(dto);
            }
        });
    }

    private List<FamilyNodeDto> buildChildFamilyList(Long parentId) {
        List<FamilyNodeDto> childFamilyList = CollUtil.newArrayList();
        List<FamilyNode> childList = nodeMapper.selectList(Wrappers.<FamilyNode>lambdaQuery().eq(FamilyNode::getIsDelete, 0).eq(FamilyNode::getParentId, parentId));
        if (CollUtil.isNotEmpty(childList)) {
            for (FamilyNode node : childList) {
                FamilyNodeDto dto = BeanUtil.copyProperties(node, FamilyNodeDto.class);
                List<FamilyNodeDto> subChildFamilyList = buildChildFamilyList(node.getNodeId());
                dto.setChildren(subChildFamilyList);
                childFamilyList.add(dto);
            }
        }
        return childFamilyList;
    }

    @Override
    public List<?> getList(FamilyClan clan) {

        return baseMapper.selectAndNodeList(clan);
    }

    @Override
    public void add(FamilyClan clan) {
        //todo:有权限得才能添加
        save(clan.setCreateBy("admin")
                .setCreateTime(LocalDateTime.now())
                .setUpdateBy("admin")
                .setUpdateTime(LocalDateTime.now()));


    }

    @Override
    public void edit(FamilyClan clan) {
        if (clan.getFamilyId() == null)
            throw new RuntimeException("没有当前节点");

        //todo:节点第几代也要跟着改
        updateById(clan.setUpdateBy("admin").setUpdateTime(LocalDateTime.now()));
    }

    @Override
    public void delById(Long familyId) {
        List<FamilyNode> familyNodes = nodeMapper.selectList(Wrappers.<FamilyNode>lambdaQuery().eq(FamilyNode::getFamilyId, familyId));
        if (CollUtil.isNotEmpty(familyNodes)) throw new RuntimeException("当前家族还有人员信息,不能删除");

        removeById(familyId);
    }

    @Override
    public List<FamilyNodeDto> getPersonAll(Long nodeId) {
        FamilyNode node = nodeMapper.selectById(nodeId);
        if (node == null) {
            return Collections.emptyList();
        }

        FamilyNodeDto nodeDto = BeanUtil.copyProperties(node, FamilyNodeDto.class);
        List<FamilyNode> childrenList = nodeMapper.selectList(Wrappers.<FamilyNode>lambdaQuery().eq(FamilyNode::getParentId, nodeId));
        Optional.ofNullable(childrenList).ifPresent(x -> nodeDto.setChildren(BeanUtil.copyToList(x, FamilyNodeDto.class)));

        if (node.getParentId() == null) {
            return CollUtil.newArrayList(nodeDto);
        }

        FamilyNode parentNode = nodeMapper.selectById(node.getParentId());
        if (parentNode == null) {
            return CollUtil.newArrayList(nodeDto);
        }

        FamilyNodeDto parentDto = BeanUtil.copyProperties(parentNode, FamilyNodeDto.class);
        parentDto.setChildren(CollUtil.newArrayList(nodeDto));

        if (parentNode.getParentId() == null) {
            return CollUtil.newArrayList(parentDto);
        }

        FamilyNode familyNode = nodeMapper.selectById(parentNode.getParentId());
        if (familyNode == null) {
            return CollUtil.newArrayList(parentDto);
        }

        FamilyNodeDto familyNodeDto = BeanUtil.copyProperties(familyNode, FamilyNodeDto.class);
        familyNodeDto.setChildren(CollUtil.newArrayList(parentDto));

        return CollUtil.newArrayList(familyNodeDto);

    }
}
